#include "image_view.h"
#include "utility.h"
//(*InternalHeaders(ImageView)
#include <wx/intl.h>
#include <wx/string.h>
#include <algorithm>
//*)
#include <wx/dcmemory.h>
#include <wx/dcclient.h>
#include "set.h"
//(*IdInit(ImageView)
//*)

BEGIN_EVENT_TABLE(ImageView,wxPanel)
	EVT_PAINT(ImageView::OnPaint)
	EVT_LEFT_DOWN(ImageView::OnLeftDown)
	EVT_LEFT_UP(ImageView::OnLeftUp)
	EVT_MOTION(ImageView::OnMove)
	EVT_ERASE_BACKGROUND(ImageView::OnBackground)
	//EVT_SET_FOCUS(ImageView::OnFocus)
END_EVENT_TABLE()

/*void ImageView::OnFocus(wxFocusEvent &event)
{
	SetActiveImageView(this);
}*/

void ImageView::OnBackground(wxEraseEvent &event)
{
    //event.Skip();
}
ImageView::ImageView(wxWindow* parent,wxWindowID id,const wxPoint& pos,const wxSize& size)
{
	//(*Initialize(ImageView)
	Create(parent, id, pos, size, wxTAB_TRAVERSAL, _T("id"));
	//*)
	m_selRect.SetX(0);
	m_selRect.SetY(0);
	m_selRect.SetWidth(0);
	m_selRect.SetHeight(0);
	m_drawSelRect = false;
}

void ImageView::SetImage(wxString &fileName)
{
    m_imageName = fileName;
    m_bmp.LoadFile(fileName,wxBITMAP_TYPE_PNG);

	SetVirtualSize(m_bmp.GetWidth(),m_bmp.GetHeight());
	SetScrollRate( 10, 10);
}
void ImageView::Draw(wxDC &dc)
{
    if(m_bmp.IsOk())
        dc.DrawBitmap(m_bmp,0,0,true);
    if(ShowGird())
    {
        wxSize gridSize = GetGridSize();
        wxSize size = dc.GetSize();
        dc.SetPen(*wxGREY_PEN);
        for(int i = 0; i < size.GetWidth()/gridSize.GetWidth(); i++)
        {
            dc.DrawLine(i*gridSize.GetWidth(),0,i*gridSize.GetWidth(),size.GetHeight());
        }
        for(int i = 0; i < size.GetHeight()/gridSize.GetHeight(); i++)
        {
            dc.DrawLine(0,i*gridSize.GetHeight(),size.GetWidth(),i*gridSize.GetHeight());
        }
    }
}
void ImageView::OnPaint(wxPaintEvent& event)
{
    wxPaintDC dc(this);
	DoPrepareDC(dc);

    wxSize clientSize = GetClientSize();
	if(m_bmp.IsOk())
	{
		if(clientSize.GetWidth() < m_bmp.GetWidth())
			clientSize.SetWidth(m_bmp.GetWidth());
		if(clientSize.GetHeight() < m_bmp.GetHeight())
			clientSize.SetHeight(m_bmp.GetHeight());
	}
    wxBitmap bmp(clientSize.GetWidth(),clientSize.GetHeight());
    wxMemoryDC memDC(bmp);
	memDC.SetBrush(*wxWHITE_BRUSH);
	memDC.DrawRectangle(clientSize);
    Draw(memDC);
    if((m_selRect.GetWidth() > 0) && (m_selRect.GetHeight() > 0))
    {
        memDC.SetBrush(*wxTRANSPARENT_BRUSH);
        memDC.SetPen(*wxRED_PEN);
        memDC.DrawRectangle(m_selRect);
    }

    dc.Blit(0,0,clientSize.GetWidth(),clientSize.GetHeight(),&memDC,0,0);
}

ImageView::~ImageView()
{
	//if(GetActiveImageView() == this)
		//SetActiveImageView(NULL);

}

void ImageView::OnLeftDown(wxMouseEvent &event)
{
	event.Skip();
	int x;
    int y;
    CalcUnscrolledPosition(event.GetX(),event.GetY(),&x,&y);

    //if((x > m_bmp.GetWidth()) || (y > m_bmp.GetHeight()))
        //return;

    m_leftDownX = x;
	m_leftDownY = y;
	m_selRect.SetX(x);
	m_selRect.SetY(y);
    
    m_selRect.SetWidth(0);
    m_selRect.SetHeight(0);
    m_drawSelRect = true;
}

void ImageView::OnLeftUp(wxMouseEvent &event)
{
    m_drawSelRect = false;
	SetSelImage(this->GetSelImage());
    Refresh();
}

void ImageView::OnMove(wxMouseEvent &event)
{
    if(!m_drawSelRect)
        return;

    int x;
    int y;
    CalcUnscrolledPosition(event.GetX(),event.GetY(),&x,&y);

    //if((x < m_selRect.GetX()) || (y < m_selRect.GetY()))
        //return;

    if(x > m_bmp.GetWidth())
        x = m_bmp.GetWidth();
    if(y > m_bmp.GetHeight())
        y = m_bmp.GetHeight();

    wxSize size = GetGridSize();
	int minx,miny,maxx,maxy;
	minx = std::min(x,m_leftDownX);
	miny = std::min(y,m_leftDownY);
	maxx = std::max(x,m_leftDownX);
	maxy = std::max(y,m_leftDownY);
    if(SnapGrid())
    {
        minx = minx/size.GetWidth()*size.GetWidth();
        miny = miny/size.GetHeight()*size.GetHeight();

		bool modx = maxx%size.GetWidth() > 0;
        if(modx)
            maxx = (maxx/size.GetWidth()+1)*size.GetWidth();
        else
            maxx = maxx/size.GetWidth()*size.GetWidth();
        bool mody = maxy%size.GetHeight() > 0;
        if(mody)
            maxy = (maxy/size.GetHeight()+1)*size.GetHeight();
        else
            maxy = maxy/size.GetHeight()*size.GetHeight();
    }
    m_selRect.SetX(minx);
	m_selRect.SetY(miny);
    m_selRect.SetWidth(maxx-minx);
    m_selRect.SetHeight(maxy-miny);

    wxClientDC dc(this);
	DoPrepareDC(dc);
    wxSize clientSize = GetClientSize();
	if(m_bmp.IsOk())
	{
		if(clientSize.GetWidth() < m_bmp.GetWidth())
			clientSize.SetWidth(m_bmp.GetWidth());
		if(clientSize.GetHeight() < m_bmp.GetHeight())
			clientSize.SetHeight(m_bmp.GetHeight());
	}
    wxBitmap bmp(clientSize.GetWidth(),clientSize.GetHeight());
    wxMemoryDC memDC(bmp);
	memDC.SetBrush(*wxWHITE_BRUSH);
	memDC.DrawRectangle(clientSize);
    Draw(memDC);
    memDC.SetBrush(*wxTRANSPARENT_BRUSH);
    memDC.SetPen(*wxRED_PEN);
    memDC.DrawRectangle(m_selRect);
    dc.Blit(0,0,clientSize.GetWidth(),clientSize.GetHeight(),&memDC,0,0);
}

SSelImage *ImageView::GetSelImage()
{
    if((m_selRect.GetWidth() == 0) || (m_selRect.GetHeight() == 0))
        return NULL;
    static SSelImage selImage;
    selImage.name = m_imageName;
    selImage.rect = m_selRect;
    return &selImage;
}
